/**
 * Package:com.goldcitynet.server.mina.session.codec;
 * $Id$
 * Copyright(c) 2001-2005 www.afteryuan.com
 */
package com.afteryuan.server.mina.codec;

import com.afteryuan.server.command.up.CommandUp;
import com.afteryuan.server.command.up.core.NullUp;
import com.afteryuan.server.command.up.core.PolicyUp;
import com.afteryuan.server.utils.Constants;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.Amf3Input;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Amf3Decoder
 * <p/>
 * <p><a href="Amf3Decoder.java.html"><i>View Source</i></a></p>
 *
 * @author <a href="mailto:afteryuan@afteryuan.com">$Author$</a>
 * @version $Revision$
 */
public class Amf3Decoder extends CumulativeProtocolDecoder {
    public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
        //标记当前位置
        in.mark();
        InputStream ins = in.asInputStream();
//        System.out.println(ins.available());
        //处理策略文件请求
        if (in.remaining() == 23) {
            byte[] policy = new byte[23];
            for (int i = 0; i < 23; i++) {
                policy[i] = in.get();
            }
            if (new String(policy).startsWith(Constants.POLICYREQUEST)) {
                out.write(new PolicyUp());
                return true;
            }
            in.reset();
        }
        //开始读取对象
        Object o = readObject(SerializationContext.getSerializationContext(), ins);
        //默认读取出的对象必须为Command,否则认为读取失败
        if (o != null && o instanceof CommandUp) {
            out.write(o);
            return true;
        } else {
            //如果读取对象失败,说明数据不完整,则将位置重置到标记处,返回false
            //CumulativeProtocolDecoder 会将剩余数据放入session中,跟下次来的数据汇合,在进行解码
            in.reset();
            return false;
        }

    }

    //调用AMF3的解码方法,读取命令对象
    private Object readObject(SerializationContext serializationContext, InputStream ins) throws IOException {
        Amf3Input amfin = new Amf3Input(serializationContext);
        amfin.setInputStream(ins);
        Object o = null;
        try {
            o = amfin.readObject();
        } catch (EOFException e) {
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new ClassCastException(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            throw new IOException(e.getMessage());
        }
        if (o instanceof ASObject) {
            return new NullUp();
        }
        return o;
    }
}
